// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: win_theme_engine.cpp
// Description: WinThemeEngine Class
//      Author: Ziming Li
//     Created: 2019-03-15
// -------------------------------------------------
// Copyright (C) 2019 MingYang Software Technology.
// -------------------------------------------------

#include "./win_theme_engine.h"

#include "blinkit/blink/renderer/platform/geometry/int_rect.h"
#include "blinkit/ui/animation/animation_frame.h"
#include "blinkit/win/theme_helpers.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorPriv.h"
#include "third_party/zed/include/zed/win/hmodule.hpp"

namespace BlinKit {

static int WINAPI GetMetricsWrapper(int index, UINT)
{
    return GetSystemMetrics(index);
}

WinThemeEngine::WinThemeEngine(void)
    : m_getMetrics(GetMetricsWrapper)
    , m_themePainter(ThemePainter::Create())
{
    m_paintSrcATop.setAntiAlias(false);
    m_paintSrcATop.setXfermodeMode(SkXfermode::kSrcATop_Mode);

    HMODULE user32 = GetModuleHandle(TEXT("User32.dll"));
    zed::hmodule::get_proc_address(user32, "GetSystemMetricsForDpi", m_getMetrics);
}

WinThemeEngine::~WinThemeEngine(void) = default;

const SkPaint* WinThemeEngine::AdjustPaint(Part part) const
{
    switch (part)
    {
        case PartCheckbox: case PartRadio: case PartButton:
        case PartTextField:
        case PartMenuList:
        case PartSliderTrack: case PartSliderThumb:
        case PartInnerSpinButton:
        case PartProgressBar:
            return &m_paintSrcATop;
    }
    return nullptr;
}

IntSize WinThemeEngine::GetViewportSize(Part part)
{
    IntSize size;
    switch (part)
    {
        case PartScrollbarDownArrow:
        case PartScrollbarUpArrow:
        case PartScrollbarVerticalThumb:
        case PartScrollbarVerticalTrack:
            size.setWidth(m_getMetrics(SM_CXVSCROLL, 96));
            if (0 == size.width())
                size.setWidth(17);
            size.setHeight(size.width());
            break;
        case PartScrollbarLeftArrow:
        case PartScrollbarRightArrow:
        case PartScrollbarHorizontalThumb:
        case PartScrollbarHorizontalTrack:
            size.setHeight(m_getMetrics(SM_CYHSCROLL, 96));
            if (0 == size.height())
                size.setHeight(17);
            size.setWidth(size.height());
            break;
        case PartCheckbox:
        case PartRadio:
            size.setWidth(13);
            size.setHeight(13);
            break;
        default:
            ASSERT_NOT_REACHED();
    }
    return size;
}

void WinThemeEngine::paint(WebCanvas *canvas, Part part, State state, const IntRect &rect, const ExtraParams *extra)
{
    if (rect.isEmpty())
        return;

    HDC hdc = CreateCompatibleDC(nullptr);

    AnimationFrame frame(rect.size());
    HGDIOBJ oldBitmap = SelectObject(hdc, frame);

    frame.BeginPaint().clear(SK_ColorTRANSPARENT);

    m_themePainter->Paint(hdc, part, state, rect, extra);

    SkBitmap &bitmap = frame.GetBitmap();
    bitmap.setImmutable();
    canvas->drawBitmap(bitmap, static_cast<SkScalar>(rect.x()), static_cast<SkScalar>(rect.y()), AdjustPaint(part));

    SelectObject(hdc, oldBitmap);
    DeleteDC(hdc);
}

} // namespace BlinKit
